#include "..\TinyVoiceCardServer\TinyTCPIF.h"
#include "..\TinyVoiceCardServer\TinyVoiceCardServerDefine.h"
#include "TinySanhuiCardPool.h"
#include "Extension.h"
#include "TrunkChannel.h"
#include <string>



CTinySanhuiCardPool::CTinySanhuiCardPool(void)
: m_initialized(false)
, m_nChannelNum(0)
{
	init();
	initAllDevice();
}

CTinySanhuiCardPool::~CTinySanhuiCardPool(void)
{
}

int CTinySanhuiCardPool::CardCallBackProc(WORD wEvent, int nReference, DWORD dwParam, DWORD dwUser)
{
	CTinySanhuiCardPool* sanhuiCardPool = (CTinySanhuiCardPool*)dwUser;

	if(sanhuiCardPool == NULL)
		return 0;

	CDevice * device = sanhuiCardPool->getDeviceByChannelID(nReference);

	if(device != NULL)
		return device->CardCallBackProc(wEvent,dwParam);
	
	return 0;
}
void CTinySanhuiCardPool::registerDevice(std::string cardID,std::string cardSN,std::string deviceType,int channelID,std::string deviceID)
{
	if(deviceType == "Trunk")
	{
		for(int i = 0; i<this->m_trunkVec.size();++i)
		{
			if(cardID == m_trunkVec[i]->GetBoardType() && cardSN ==  m_trunkVec[i]->GetBoardSN() && channelID == m_trunkVec[i]->getChannelID())
			{
				m_trunkVec[i]->setDeviceID(deviceID);
				g_Logger.log(debug1,"Trunk device:"+deviceID+" registered");
				return;
			}
		}

	}
	if(deviceType == "Extension")
	{
		for(int i = 0; i<this->m_userVec.size();++i)
		{
			if(cardID == m_userVec[i]->GetBoardType() && cardSN ==  m_userVec[i]->GetBoardSN() && channelID == m_userVec[i]->getChannelID())
			{
				m_userVec[i]->setDeviceID(deviceID);
				g_Logger.log(debug1,"User device:"+deviceID+" registered");
				return;
			}
		}

	}
}

//process and dispatch msg
void  CTinySanhuiCardPool::ProcessReceivedMsg(CTinyMsg &inMsg,CTinyMsg &OutMsg)
{
	switch(inMsg.getMsgIndex())
		{
		case VOICECARD_ACTION:
			switch(inMsg.getMsgItem())
			{
			case VOICECARD_REGISTDEVICE_ERROR:
				//stopTimer
				//g_TimerPool.stopTimer(m_CardTimer);
				break;
			case VOICECARD_REGISTDEVICE_SUCC:
				{
					std::string moduleName,deviceType,cardtype,cardsn,channelId,deviceID;
					inMsg.getDefaultParamByIndex(VOICECARD_REGISTDEVICE_SUCC_MODULENAME,moduleName);
					inMsg.getDefaultParamByIndex(VOICECARD_REGISTDEVICE_SUCC_DEVICETYPE,deviceType);
					inMsg.getDefaultParamByIndex(VOICECARD_REGISTDEVICE_SUCC_CARDTYPE,cardtype);
					inMsg.getDefaultParamByIndex(VOICECARD_REGISTDEVICE_SUCC_CARDSN,cardsn);
					inMsg.getDefaultParamByIndex(VOICECARD_REGISTDEVICE_SUCC_CHANNELID,channelId);
					inMsg.getDefaultParamByIndex(VOICECARD_REGISTDEVICE_SUCC_REGDEVICEID,deviceID);
					registerDevice(cardtype,cardsn,deviceType,atoi(channelId.c_str()),deviceID);
				}
				break;
			case VOICECARD_PICKUP:
				{
					//pickup and upload connected msg
					std::string moduleName,deviceType,deviceID;

					inMsg.getDefaultParamByIndex(VOICECARD_PICKUP_MODULENAME,moduleName);
					inMsg.getDefaultParamByIndex(VOICECARD_PICKUP_DEVICEID,deviceID);
					inMsg.getDefaultParamByIndex(VOICECARD_PICKUP_DEVICETYPE,deviceType);

					CDevice* device = getDeviceByID(deviceID);
					if(device != NULL)
						device->ProcessReceivedMsg(inMsg,OutMsg);
					g_Logger.log(debug1,"can not found device by deviceID = "+deviceID);
				}break;
			default:
				break;
			};
			break;
	};
}

bool CTinySanhuiCardPool::init(void)
{
	//init hardware first
	int nIsSsmStartCtiOK = SsmStartCti("ShConfig.ini", "ShIndex.ini");

	if(nIsSsmStartCtiOK != 0)
	{
		SsmGetLastErrMsg(szErrMsg);
		m_initialized = false;
		return false;
	}

	if(SsmGetMaxUsableBoard() != SsmGetMaxCfgBoard())
	{
		SsmGetLastErrMsg(szErrMsg);
		m_initialized = false;
		return false;
	}

	// set event callback handle.
	EVENT_SET_INFO EventSet;
	EventSet.dwWorkMode = EVENT_CALLBACK;	
	EventSet.lpHandlerParam = CardCallBackProc;
	EventSet.dwUser = (DWORD)this;
	SsmSetEvent(0xffff, -1, true, &EventSet);
	//nTimer = SsmStartTimer(200, 1);
	
	//other init
	g_TimerPool.requestTimer(this,m_DeviceRegisterTimer,&CTinySanhuiCardPool::processTimer,5000,true);

	//set flag
	m_initialized = true;
	return true;
}

void CTinySanhuiCardPool::processTimer(std::string timerID)
{
	if(m_DeviceRegisterTimer == timerID)
	{
		//check serverConnection
		if(g_TinyTCPIF.checkServerConn() == true)
		{
			//get DeviceID from Server
			CTinyMsg msg;
			char str[10];
			bool stillReg = false;
			for( int i =0; i<m_trunkVec.size();++i)
			{
				if(m_trunkVec[i]->getDeviceID() != "")
					continue;
				stillReg = true;
				msg.setMsgIndex(VOICECARD_ACTION);
				msg.setMsgItem(VOICECARD_REGISTDEVICE);
				msg.setDefaultParam(VOICECARD_REGISTDEVICE_MODULENAME,g_Config.getConfig()->m_InstanceName);
				msg.setDefaultParam(VOICECARD_REGISTDEVICE_CARDTYPE,m_trunkVec[i]->GetBoardType());
				msg.setDefaultParam(VOICECARD_REGISTDEVICE_CARDSN,m_trunkVec[i]->GetBoardSN());
				msg.setDefaultParam(VOICECARD_REGISTDEVICE_CHANNELID,_itoa(m_trunkVec[i]->m_ChannelID,str,10));
			    msg.setDefaultParam(VOICECARD_REGISTDEVICE_DEVICETYPE,"Trunk");
				g_TinyTCPIF.sendServerMsg(msg);
			}
			for( int j = 0; j< m_userVec.size();++j )
			{
				if(m_userVec[j]->getDeviceID() != "")
					continue;
				stillReg = true;
				msg.setMsgIndex(VOICECARD_ACTION);
				msg.setMsgItem(VOICECARD_REGISTDEVICE);
				msg.setDefaultParam(VOICECARD_REGISTDEVICE_MODULENAME,g_Config.getConfig()->m_InstanceName);
				msg.setDefaultParam(VOICECARD_REGISTDEVICE_CARDTYPE,m_userVec[j]->GetBoardType());
				msg.setDefaultParam(VOICECARD_REGISTDEVICE_CARDSN,m_userVec[j]->GetBoardSN());
				msg.setDefaultParam(VOICECARD_REGISTDEVICE_CHANNELID,_itoa(m_userVec[j]->m_ChannelID,str,10));
				msg.setDefaultParam(VOICECARD_REGISTDEVICE_DEVICETYPE,"Extension");
				g_TinyTCPIF.sendServerMsg(msg);
			}
			if(stillReg == false)
				g_TimerPool.stopTimer(timerID);
		}

	}
}

void CTinySanhuiCardPool::initAllDevice(void)
{
	m_nChannelNum =SsmGetMaxCh();
	m_trunkVec.clear();
	m_userVec.clear();

	int boardcount = SsmGetMaxCfgBoard();
	int boardmodel = 0;
	DWORD boardnum = 0;
	std::vector<std::string> vboardmodel;
	std::vector<std::string> vboardtype;
	char buffer[128];

	for(int i =1;i<=boardcount;++i)
	{
		 boardmodel = SsmGetBoardModel(i-1);
		 std::string type = getBoardType(boardmodel);
		 vboardmodel.push_back(type);
		 boardnum = SsmGetPciSerialNo(i-1);
		 sprintf_s(buffer,128,"%d",boardnum);
		 vboardtype.push_back(buffer);
	}

	for(int i=0; i<m_nChannelNum; i++)
	{
		if(SsmGetChType(i) == 2 ) // user channel
		{
			SsmSetASDT(i, 1);
			CExtension *tempExt = new CExtension();
			tempExt->changeState(Device_State_ExtIdle);

			int pnBId,pnBCh;
			int ret = SsmGetChHdInfo(i, &pnBId, &pnBCh);
			if(ret == 0)
			{
				tempExt->SetBoardSN(vboardtype[pnBId]);
				tempExt->SetBoardType(vboardmodel[pnBId]);
			}
			tempExt->setDeviceID("");
			tempExt->setChannelID(i);
			m_userVec.push_back(tempExt);
		}
		if(SsmGetChType(i) == 0 ) // analogue trunk channel
		{
			int nDirection;
			CTrunkChannel *tempTrunk = new CTrunkChannel();
			if( SsmGetAutoCallDirection(i,&nDirection) == 1 ) //auto connection is supported
			{
				if( nDirection == 0 || nDirection == 2 ) //enable call in
				{
					tempTrunk->changeState(Device_State_TrunkIdle);				  
					tempTrunk->m_EnCalled = true;
					int pnBId,pnBCh;
					int ret = SsmGetChHdInfo(i, &pnBId, &pnBCh);
					if(ret == 0)
					{
						tempTrunk->SetBoardSN(vboardtype[pnBId]);
						tempTrunk->SetBoardType(vboardmodel[pnBId]);
					}
					tempTrunk->setDeviceID("");
					tempTrunk->setChannelID(i);
				}
			}
			m_trunkVec.push_back(tempTrunk);
		}//end else
	}//end for
}

std::string CTinySanhuiCardPool::getBoardType(int index)
{
	if(index == 0x60)
		return "SHT-4B/USB";
	else
		return "Unknown";
}
CDevice* CTinySanhuiCardPool::getDeviceByChannelID(int id)
{
	if(id<0)
		return NULL;

	for(unsigned int i=0;i<m_trunkVec.size();++i)
	{
		if(m_trunkVec[i]->getChannelID() == id)
			return m_trunkVec[i];
	}
	for(unsigned int i=0;i<m_userVec.size();++i)
	{
		if(m_userVec[i]->getChannelID() == id)
			return m_userVec[i];
	}
	return NULL;
}

CDevice* CTinySanhuiCardPool::getDeviceByID(std::string deviceID)
{
	if(deviceID == "")
		return NULL;
	for(unsigned int i=0;i<m_trunkVec.size();++i)
	{
		if(m_trunkVec[i]->getDeviceID() == deviceID)
			return m_trunkVec[i];
	}
	for(unsigned int i=0;i<m_userVec.size();++i)
	{
		if(m_userVec[i]->getDeviceID() == deviceID)
			return m_userVec[i];
	}
	return NULL;
}
